//---------------------------------------------------------------------------
//	Greenplum Database
//	Copyright (C) 2012 EMC Corp.
//
//	@filename:
//		CXformCTEAnchor2TrivialSelect.cpp
//
//	@doc:
//		Implementation of transform
//---------------------------------------------------------------------------

#include "spqopt/xforms/CXformCTEAnchor2TrivialSelect.h"

#include "spqos/base.h"

#include "spqopt/operators/CLogicalCTEAnchor.h"
#include "spqopt/operators/CLogicalSelect.h"
#include "spqopt/operators/CPatternLeaf.h"
#include "spqopt/xforms/CXformUtils.h"

using namespace spqopt;


//---------------------------------------------------------------------------
//	@function:
//		CXformCTEAnchor2TrivialSelect::CXformCTEAnchor2TrivialSelect
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CXformCTEAnchor2TrivialSelect::CXformCTEAnchor2TrivialSelect(CMemoryPool *mp)
	: CXformExploration(
		  // pattern
		  SPQOS_NEW(mp) CExpression(
			  mp, SPQOS_NEW(mp) CLogicalCTEAnchor(mp),
			  SPQOS_NEW(mp) CExpression(mp, SPQOS_NEW(mp) CPatternLeaf(mp))))
{
}

//---------------------------------------------------------------------------
//	@function:
//		CXformCTEAnchor2TrivialSelect::Exfp
//
//	@doc:
//		Compute promise of xform
//
//---------------------------------------------------------------------------
CXform::EXformPromise
CXformCTEAnchor2TrivialSelect::Exfp(CExpressionHandle &exprhdl) const
{
	ULONG id = CLogicalCTEAnchor::PopConvert(exprhdl.Pop())->Id();
	CCTEInfo *pcteinfo = COptCtxt::PoctxtFromTLS()->Pcteinfo();
	const ULONG ulConsumers = pcteinfo->UlConsumers(id);
	SPQOS_ASSERT(0 < ulConsumers);

	if ((pcteinfo->FEnableInlining() || 1 == ulConsumers) &&
		CXformUtils::FInlinableCTE(id))
	{
		return CXform::ExfpHigh;
	}

	return CXform::ExfpNone;
}

//---------------------------------------------------------------------------
//	@function:
//		CXformCTEAnchor2TrivialSelect::Transform
//
//	@doc:
//		Actual transformation
//
//---------------------------------------------------------------------------
void
CXformCTEAnchor2TrivialSelect::Transform(CXformContext *pxfctxt,
										 CXformResult *pxfres,
										 CExpression *pexpr) const
{
	SPQOS_ASSERT(NULL != pxfctxt);
	SPQOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
	SPQOS_ASSERT(FCheckPattern(pexpr));

	// ExfExpandFullOuterJoin converts a LogicalFullJoin to a CTE with a UnionAll
	// of an LOJ and LASJ. Even if expansion is disabled by the trace flag, the
	// xform still needs to be triggered, so that the CTE operator generated
	// can be used to compute the statistics for the logical merge join group (see
	// CLogicalFullOuterJoin::Esp()).
	// Instead, we skip the implementation of the CTE, here, if the trace flag is
	// disabled and the CTE op was generated by ExfExpandFullOuterJoin.
	CGroupExpression *pgexprOrigin = pexpr->Pgexpr();
	if (!SPQOS_FTRACE(EopttraceExpandFullJoin) && NULL != pgexprOrigin &&
		CXform::ExfExpandFullOuterJoin == pgexprOrigin->ExfidOrigin())
	{
		return;
	}

	CMemoryPool *mp = pxfctxt->Pmp();

	// child of CTE anchor
	CExpression *pexprChild = (*pexpr)[0];
	pexprChild->AddRef();

	CExpression *pexprSelect = SPQOS_NEW(mp)
		CExpression(mp, SPQOS_NEW(mp) CLogicalSelect(mp), pexprChild,
					CUtils::PexprScalarConstBool(mp, true /*fValue*/));

	pxfres->Add(pexprSelect);
}

// EOF
